package cn.growthgate.fgo.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.springframework.web.multipart.MultipartFile;

import cn.growthgate.fgo.core.shiro.SimpleUser;
import cn.growthgate.fgo.entity.Image;
import cn.growthgate.fgo.service.IImageService;
import net.coobird.thumbnailator.Thumbnails;

/**
 * 图片工具类
 * 
 * @author GrowthGate
 * @since 2019年4月21日
 *
 */
public class ImageUtils {

	/**
	 * 上传图片
	 * 
	 * @param multipartFile
	 * @return
	 */
	public static Image uploadImage(MultipartFile multipartFile) {
		IImageService service = SpringUtils.getBean(IImageService.class);
		File file = FileUtils.uploadFile(multipartFile);
		if (file == null) {
			return null;
		}
		Calendar now = Calendar.getInstance();
		SimpleUser user = AuthenticationUtils.getLoginSimpleUser();
		Map<String, Integer> resolution = new HashMap<>();
		try {
			resolution = getResolution(file);
		} catch (IOException e) {
			e.printStackTrace();
		}

		Image image = new Image();
		// 随机唯一id
		String uuid;
		do {
			uuid = StringUtils.getRandomUUID();
			image.setUuid(uuid);
		} while (service.getByUUID(uuid) != null);
		image.setName(multipartFile.getOriginalFilename());
		image.setPath(FileUtils.getRelativePath(file));
		image.setLength(file.length());
		image.setHeight(resolution.get("height"));
		image.setWidth(resolution.get("width"));
		image.setYear(now.get(Calendar.YEAR));
		image.setMonth(now.get(Calendar.MONTH) + 1);
		image.setDay(now.get(Calendar.DAY_OF_MONTH));
		if (user != null) {
			image.setUserId(user.getId());
		}
		// 保存
		return service.insert(image) ? image : null;
	}

	/**
	 * 获取图片url
	 * 
	 * @param uuid
	 * @return
	 */
	public static String getImageUrl(String uuid) {
		return "/image/" + uuid;
	}

	/**
	 * 获取图片url
	 * 
	 * @param uuid
	 * @param pixel
	 * @return
	 */
	public static String getImageUrl(String uuid, Integer pixel) {
		return "/image/" + uuid + "?pixel=" + pixel;
	}

	/**
	 * 获取图片url
	 * 
	 * @param image
	 * @return
	 */
	public static String getImageUrl(Image image) {
		return getImageUrl(image.getUuid());
	}

	/**
	 * 获取分辨率
	 * 
	 * @param image
	 * @return width 宽 height 高
	 * @throws IOException
	 */
	public static Map<String, Integer> getResolution(File image) throws IOException {
		BufferedImage bufferedImage = ImageIO.read(image);
		Map<String, Integer> map = new HashMap<>();
		map.put("width", bufferedImage.getWidth());
		map.put("height", bufferedImage.getHeight());
		return map;
	}

	/**
	 * 按图片比例进行缩放，使新的图片宽、高不大于指定值
	 * 
	 * @param image
	 *            需要缩放的图片
	 * @param width
	 *            缩放宽度
	 * @param height
	 *            缩放高度
	 * @return 新图片
	 * @throws IOException
	 */
	public static BufferedImage scaleAsBufferedImage(File image, int width, int height) throws IOException {
		return Thumbnails.of(image).size(width, height).outputQuality(1).asBufferedImage();
	}

	/**
	 * 按图片比例进行缩放，使新的图片宽、高不大于指定值
	 * 
	 * @param os
	 *            输出流
	 * @param image
	 *            需要缩放的图片
	 * @param width
	 *            缩放宽度
	 * @param height
	 *            缩放高度
	 * @throws IOException
	 */
	public static void scaleToOutputStream(OutputStream os, File image, int width, int height) throws IOException {
		Thumbnails.of(image).size(width, height).outputQuality(1).toOutputStream(os);
	}

	/**
	 * 按图片比例进行缩放，使新的图片为宽、高均大于等于指定值的最小图片（作为div背景使用）
	 * 
	 * @param image
	 *            需要缩放的图片
	 * @param width
	 *            缩放宽度
	 * @param height
	 *            缩放高度
	 * @return 新图片
	 * @throws IOException
	 */
	public static BufferedImage scaleBackgroundAsBufferedImage(File image, int width, int height) throws IOException {
		Map<String, Integer> resolution = generateBackgroundResolution(image, width, height);
		return scaleAsBufferedImage(image, resolution.get("width"), resolution.get("height"));
	}

	/**
	 * 按图片比例进行缩放，使新的图片宽、高不大于指定值
	 * 
	 * @param os
	 *            输出流
	 * @param image
	 *            需要缩放的图片
	 * @param width
	 *            缩放宽度
	 * @param height
	 *            缩放高度
	 * @throws IOException
	 */
	public static void scaleBackgroundToOutputStream(OutputStream os, File image, int width, int height)
			throws IOException {
		Map<String, Integer> resolution = generateBackgroundResolution(image, width, height);
		scaleToOutputStream(os, image, resolution.get("width"), resolution.get("height"));
	}

	/**
	 * 生成背景图宽高
	 * 
	 * @param image
	 * @param width
	 * @param height
	 * @return
	 * @throws IOException
	 */
	private static Map<String, Integer> generateBackgroundResolution(File image, int width, int height)
			throws IOException {
		// 获取图片宽高
		Map<String, Integer> resolution = getResolution(image);
		BigDecimal imgWidth = BigDecimal.valueOf(resolution.get("width"));
		BigDecimal imgHeight = BigDecimal.valueOf(resolution.get("height"));
		// 获取图片调整至指定宽高时需要缩放的比例
		BigDecimal widthRatio = BigDecimal.valueOf(width).divide(imgWidth, 10, BigDecimal.ROUND_HALF_UP);
		BigDecimal heightRatio = BigDecimal.valueOf(height).divide(imgHeight, 10, BigDecimal.ROUND_HALF_UP);
		// 获取比例较大值，确保缩略图最终宽高一定大于等于指定值
		BigDecimal maxRatio = widthRatio.max(heightRatio);
		// 获取缩略图宽高并生成缩略图
		int finalWidth = imgWidth.multiply(maxRatio).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
		int finalHeight = imgHeight.multiply(maxRatio).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
		Map<String, Integer> map = new HashMap<>();
		map.put("width", finalWidth);
		map.put("height", finalHeight);
		return map;
	}

}
